package cn.lijiajia3515.cairo.auth.framework.security.oauth2.server.authorization;

import lombok.Setter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.util.Assert;

import java.time.Duration;

public class RedisOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService {
	private static final String SPLIT = ":";

	@Setter
	private Duration expire = Duration.ofMinutes(30);

	@Setter
	private String namespace = "spring";

	private static final String AUTHORIZATION_CONSENT_KEY = "authorization_consent";

	private final RedisTemplate<String, Object> redisTemplate;

	public RedisOAuth2AuthorizationConsentService(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	@Override
	public void save(OAuth2AuthorizationConsent authorizationConsent) {
		Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
		redisTemplate.opsForValue().set(getKey(authorizationConsent), authorizationConsent, expire);
	}

	@Override
	public void remove(OAuth2AuthorizationConsent authorizationConsent) {
		Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
		redisTemplate.delete(getKey(authorizationConsent));
	}

	@Override
	@Nullable
	public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
		Assert.hasText(registeredClientId, "registeredClientId cannot be empty");
		Assert.hasText(principalName, "principalName cannot be empty");
		return (OAuth2AuthorizationConsent) redisTemplate.opsForValue().get(getKey(registeredClientId, principalName));
	}

	private String getKey(String registeredClientId, String principalName) {
		return String.join(SPLIT, namespace, AUTHORIZATION_CONSENT_KEY, registeredClientId, principalName);
	}

	private String getKey(OAuth2AuthorizationConsent authorizationConsent) {
		return getKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());
	}

	private String getTokenKey(OAuth2AuthorizationConsent authorizationConsent) {
		return getKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());
	}
}
